#include "common.h"
#include "font.h"
#include "i2c2.h"
#include "oled_ssd1306.h"


int oled_ssd1306::oled_i2c_write(unsigned char slave, unsigned char reg, unsigned char data)
{
    int ret;
    ret = i2c_write(slave, reg, data);
    if (ret != 0) {
        printf("atlas_i2c_write oled fail!\n");
        return -1;
    }
    return 0;
}

void oled_ssd1306::oled_clear()
{
    for(int i=0;i<8;i++)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xb0+i);
        oled_i2c_write(OLEDADDR,WRITECMD,0x00);
        oled_i2c_write(OLEDADDR,WRITECMD,0x10);
        for(int n=0;n<128;n++)
        {
            oled_i2c_write(OLEDADDR,WRITEDAYA,0x00);
        }
    }
}

void oled_ssd1306::oled_showPicture(const unsigned char BMP[])
{
    int j = 0;;
    for(int y=0;y<8;y++)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xb0+y);
        oled_i2c_write(OLEDADDR,WRITECMD,((0x00&0xf0)>>4)|0x10);
        oled_i2c_write(OLEDADDR,WRITECMD,(0x00&0x0f)|0x01);
        for (int x = 0; x < 128; x++)
        {
            oled_i2c_write(OLEDADDR,WRITEDAYA,BMP[j]);
            j++;
        }
    }
}

//颜色反显函数 0为正常显示 1为反色
void oled_ssd1306::ColorTurn(unsigned char arg)
{
    if(arg == NORMAL_COLOR)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xA6);//正常显示
    }
    if(arg == TURNOVER_COLOR)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xA7);//反色显示
    }
}

//显示翻转函数 0为正常 1为翻转
//注：这个翻转只是上下翻转，不是旋转180
void oled_ssd1306::DisplayTurn(unsigned char arg)
{
    if(arg == NORMAL_DISPLAY)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xC8);//正常显示
        oled_i2c_write(OLEDADDR,WRITECMD,0xA1);
    }
    if(arg == TURNOVER_DISPLAY)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xC0);//翻转显示
        oled_i2c_write(OLEDADDR,WRITECMD,0xA0);
    }
}

//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
void oled_ssd1306::ShowString(unsigned char x,unsigned char y,unsigned char *c,CHAR_SIZE size)
{
    while ((*c>=' ')&&(*c<='~')) //判断不是非法字符
    {
        ShowChar(x,y,*c,size);
        x+=size/2;
        if(x>(128-size))  //换行
        {
            x=0;
            y+=2;
        }
        c++;
    }  
}

//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
void oled_ssd1306::ShowString(unsigned char x,unsigned char y,const char *c,CHAR_SIZE size)
{
    printf(" size:%d\n",size);
    while ((*c>=' ')&&(*c<='~')) //判断不是非法字符
    {
        ShowChar(x,y,*c,size);
        x+=size/2;
        if(x>(128-size))  //换行
        {
            x=0;
            y+=2;
        }
        c++;
    }  
}


//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size:选择字体 12/16/24
//取模方式 逐列式
void oled_ssd1306::ShowChar(unsigned char x,unsigned char y,unsigned char c,CHAR_SIZE size)
{
    int oneCharNum = 0;
    unsigned char temp;
    int y0 = y;
    unsigned int offset = c - ' '; //计算偏移后的值
    oneCharNum = (size/8+((size%8)?1:0))*(size/2);
    for(int i=0;i<oneCharNum;i++)
    {
        if(size == size1206)
            temp = asc2_1206[offset][i];
        else if(size == size1608)
            temp = asc2_1608[offset][i];
        else if(size == size2412)
            temp = asc2_2412[offset][i];
        for(int m=0;m<8;m++)
        {
            if(temp&0x80)
                DrawPoint(x,y);
            else
                ClearPoint(x,y);
            temp<<=1;
            y++;
            if((y-y0) == size)
            {
                y = y0;
                x++;
                break;
            }
        }
    }
}


//画线
//x:0~128
//y:0~64
void oled_ssd1306::DrawLine(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2)
{
    unsigned i,k,k1,k2,y0;
    if((x1<0)||(x2>128)||(y1<0)||(y2>64)||(x1>x2)||(y1>y2))
        return;
    if(x1==x2) //画竖线
    {
        for(i=0;i<(y2-y1);i++)
        {
            DrawPoint(x1,y1+i);
        }
    }
    else if(y1==y2)   //画横线
	{
		for(i=0;i<(x2-x1);i++)
		{
			DrawPoint(x1+i,y1);
		}
    }
    else      //画斜线
	{
		k1=y2-y1;
		k2=x2-x1;
		k=k1*10/k2;
		for(i=0;i<(x2-x1);i++)
		{
			DrawPoint(x1+i,y1+i*k/10);
		}
	}
}

//x,y:圆心坐标
//r:圆的半径
void oled_ssd1306::DrawCircle(unsigned char x,unsigned char y,unsigned char r)
{
    int a,b,num;
    a=0;
    b=r;
    while(2*b*b>=r*r)
    {
        DrawPoint(x+a,y-b);
        DrawPoint(x-a,y-b);
        DrawPoint(x-a,y+b);
        DrawPoint(x+a,y+b);

        DrawPoint(x+b,y+a);
        DrawPoint(x+b,y-a);
        DrawPoint(x-b,y-a);
        DrawPoint(x-b,y+a);

        a++;
        num = (a*a+b*b)-r*r;//计算画的点离圆心的距离
        if(num>0)
        {
            a--;
            b--;
        }
    }
}

//画点 
//x:0~127
//y:0~63
void oled_ssd1306::DrawPoint(unsigned char x,unsigned char y)
{
    oledBuffer[x][y/8] |= (1<<(y%8));
}
//清除一个点
//x:0~127
//y:0~63
void oled_ssd1306::ClearPoint(unsigned char x,unsigned char y)
{
    oledBuffer[x][y/8] =~ oledBuffer[x][y/8];
    oledBuffer[x][y/8] |= (1<<(y%8));
    oledBuffer[x][y/8] =~ oledBuffer[x][y/8];
}

//更新缓冲区的数据到OLED
void oled_ssd1306::Refresh()
{
    printf("reflash oled!\n");
    for(int i=0;i<8;i++)
    {
        oled_i2c_write(OLEDADDR,WRITECMD,0xb0+i);
        oled_i2c_write(OLEDADDR,WRITECMD,0x00);
        oled_i2c_write(OLEDADDR,WRITECMD,0x10);
        for(int j=0;j<128;j++)
        {
            oled_i2c_write(OLEDADDR,WRITEDAYA,oledBuffer[j][i]);
        }
    }
}


void oled_ssd1306::oledInit()
{
    oled_i2c_write(OLEDADDR,WRITECMD,0xAE);
    oled_i2c_write(OLEDADDR,WRITECMD,0x00);
    oled_i2c_write(OLEDADDR,WRITECMD,0x10);
    oled_i2c_write(OLEDADDR,WRITECMD,0x40);
    oled_i2c_write(OLEDADDR,WRITECMD,0x81);
    oled_i2c_write(OLEDADDR,WRITECMD,0xCF);
    oled_i2c_write(OLEDADDR,WRITECMD,0xA1);

    oled_i2c_write(OLEDADDR,WRITECMD,0xC8);
    oled_i2c_write(OLEDADDR,WRITECMD,0xA6);
    oled_i2c_write(OLEDADDR,WRITECMD,0xA8);
    oled_i2c_write(OLEDADDR,WRITECMD,0x3f);
    oled_i2c_write(OLEDADDR,WRITECMD,0xD3);
    oled_i2c_write(OLEDADDR,WRITECMD,0x00);
    oled_i2c_write(OLEDADDR,WRITECMD,0xd5);

    oled_i2c_write(OLEDADDR,WRITECMD,0x80);
    oled_i2c_write(OLEDADDR,WRITECMD,0xD9);
    oled_i2c_write(OLEDADDR,WRITECMD,0xF1);
    oled_i2c_write(OLEDADDR,WRITECMD,0xDA);
    oled_i2c_write(OLEDADDR,WRITECMD,0x12);
    oled_i2c_write(OLEDADDR,WRITECMD,0xDB);
    oled_i2c_write(OLEDADDR,WRITECMD,0x40);
    
    oled_i2c_write(OLEDADDR,WRITECMD,0x20);
    oled_i2c_write(OLEDADDR,WRITECMD,0x02);
    oled_i2c_write(OLEDADDR,WRITECMD,0x8D);
    oled_i2c_write(OLEDADDR,WRITECMD,0x14);
    oled_i2c_write(OLEDADDR,WRITECMD,0xA4);
    oled_i2c_write(OLEDADDR,WRITECMD,0xA6);
    oled_i2c_write(OLEDADDR,WRITECMD,0xAF);

    oled_clear();
}

oled_ssd1306::oled_ssd1306(/* args */)
{
    oledInit();
    memset(oledBuffer,0x00,128*8*sizeof(unsigned char));
}

oled_ssd1306::~oled_ssd1306()
{
}